import argparse
import re
import copy

class Sudoku (object):
    def __init__ (self, a=None):
        self._board = [[0 for x in range (9)] for y in range (9)]
        self._p = None
        self._args = a

    def load (self, fl):
        d = ''
        with open (fl, 'r') as f:
            d = f.read ()
        return self.loads (d)

    def _pat (self):
        if self._p is None:
            self._p = re.compile ('([0-9 ]) ([0-9 ]) ([0-9 ]) ([0-9 ]) ([0-9 ]) ([0-9 ]) ([0-9 ]) ([0-9 ]) ([0-9 ])')
        return self._p

    def loads (self, s):
        lines = filter (lambda x: len (x), s.split ('\n'))
        for r, l in enumerate (lines):
            m = self._pat ().match (l)
            for c, d in enumerate (m.groups()):
                if d != ' ':
                    self._board[r][c] = int (d)

    def solve (self):
        b = copy.deepcopy (self._board)
        self.print_sol (b)
        self.bf (b, 0, 0)

    def bf (self, b, x, y):
        if not b[x][y]:
            ls = range (1, 10)
        else:
            ls = [b[x][y]]

        for i in ls:
            b[x][y] = i
            if self.is_consistant (b, x, y):
                if self._args.debug:
                    print b[x][y], x, y, ls
                    import pdb; pdb.set_trace ()
                if x == y and x == 8:
                    self.print_sol (b)
                else:
                    if y == 8:
                        #self.print_sol (b)
                        self.bf (b, x+1, 0)
                    else:
                        self.bf (b, x, y+1)
        if 1 != len (ls):
            b[x][y] = 0

    def print_sol (self, b):
        print '-'*80,'\nSol:\n', '-'*80
        for row in b:
            s = ''
            for col in row:
                if col:
                    s += ' %1d' % col
                else:
                    s += '  '
            print '%s\n' % s
        print '\n', '-'*80

    def is_consistant (self, b, x, y):
        return self.is_consistant_row (b, x, y) and self.is_consistant_col (
            b, x, y) and self.is_consistant_cell (b, x, y)

    def is_consistant_row (self, b, x, y):
        for i in range (8):
            if i != y:
                if b[x][y] == b[x][i]:
                    return False
        return True

    def is_consistant_col (self, b, x, y):
        for i in range (8):
            if i != x:
                if b[x][y] == b[i][y]:
                    return False
        return True

    def is_consistant_cell (self, b, x, y):
        cx, cy = self.find_cell (x, y)
        for r in range (3):
            for c in range (3):
                if (cx+r, cy+c) != (x, y):
                    if b[x][y] == b[cx+r][cy+c]:
                        return False
        return True
        
    def find_cell (self, x, y):
        return [3 * i for i in (x/3, y/3)]

def main ():
    parser = argparse.ArgumentParser()
    parser.add_argument('files', nargs='+', help='suduku files')
    parser.add_argument('--debug', type=int, default=0, help='debug lebel')

    args = parser.parse_args()

    for f in args.files:
        s = Sudoku (args)
        s.load (f)
        s.solve ()

if __name__ == '__main__':
    main ()
